import datetime
from gis.common import track_logging

from django.db import transaction
from django.db.models import Sum

from itpay.core.agency import agency_service
from itpay.core.recharge_order import recharge_comment_service, order_service
from .const import *
from .models import AccountScoreDetail

_LOGGER = track_logging.getLogger(__name__)


def add_agency_score_detail(agency_id, score, event_type, event_id, mch_id=None, user_id=None, remark=None):
    """
    修改代理分数
    :return:
    """
    assert isinstance(event_type, AgencyScoreEventType)

    with transaction.atomic():
        agency = agency_service.get_agency_model_with_lock(agency_id)

        agency.score += score
        agency.save()

        AccountScoreDetail.objects.create(agency=agency, score=score, after_score=agency.score,
                                          mch_id=mch_id, user_id=user_id,
                                          event_type=event_type.value, event_id=event_id,
                                          remark=remark)


def calculate_order_amount_score(order_amount):
    """
    根据订单金额，计算能获得的分数
    :param order_amount:
    :return:
    """
    assert order_amount >= 0
    assert isinstance(ORDER_AMOUNT_SCORE_CONF, list)
    for amount, score in sorted(ORDER_AMOUNT_SCORE_CONF, reverse=True):
        if order_amount >= amount:
            return score
    return 0


def get_daily_user_make_score_for_agency(mch_id, user_id, agency_id, date=None):
    """
    获取用户为代理贡献的分数，默认今天
    """
    if not date:
        date = datetime.date.today()

    return AccountScoreDetail.objects.filter(user_id=user_id, mch_id=mch_id, agency_id=agency_id,
                                             created_at__date=date).aggregate(Sum('score'))['score__sum'] or 0


def get_order_comment_score(comment_id):
    comment = recharge_comment_service.get_comment_by_id(comment_id)
    return ORDER_COMMENT_SCORE_CONF[OrderCommentRank(comment['comment_rank'])]


def get_order_chase_score(order_id):
    order = order_service.get_order_by_id(order_id)
    score = -calculate_order_amount_score(order['chased_amount'])
    return score


def get_order_recharge_score(order_id):
    order = order_service.get_order_by_id(order_id)
    score = calculate_order_amount_score(order['real_amount'])
    return score


SCORE_HANDLER = {
    AgencyScoreEventType.ORDER_COMMENT: get_order_comment_score,
    AgencyScoreEventType.ORDER_CHASE: get_order_chase_score,
    AgencyScoreEventType.ORDER_RECHARGE: get_order_recharge_score
}


def get_score(event_type, event_id):
    return SCORE_HANDLER[event_type](event_id)


def update_agency_score(agency_id, event_type, event_id, mch_id=None, user_id=None, remark=None):
    assert isinstance(event_type, AgencyScoreEventType)

    _LOGGER.info(
        "user change agency score limit {} {} {} {} {} {}".format(agency_id, event_type, event_id, mch_id,
                                                                  user_id, remark))
    score = get_score(event_type, event_id)
    if agency_id and mch_id and user_id:
        today_score = get_daily_user_make_score_for_agency(mch_id, user_id, agency_id)
        if today_score + score < DAILY_SCORE_LIMIT['lower_limit']:
            score = min(DAILY_SCORE_LIMIT['lower_limit'] - today_score, 0)
            _LOGGER.info(
                "user change agency score lower limit {} {} {} {} {} {} {}".format(agency_id, event_type, event_id,
                                                                                   mch_id, user_id, today_score, score))
        if today_score + score > DAILY_SCORE_LIMIT['upper_limit']:
            score = max(DAILY_SCORE_LIMIT['upper_limit'] - today_score, 0)
            _LOGGER.info(
                "user change agency score upper limit {} {} {} {} {} {} {}".format(agency_id, event_type, event_id,
                                                                                   mch_id, user_id, today_score, score))

    add_agency_score_detail(agency_id, score, event_type, event_id, mch_id=mch_id, user_id=user_id, remark=remark)
